package com.example.pcbackend.service.impl;

import com.example.pcbackend.config.UserContext;
import com.example.pcbackend.enums.QrCodeStatusEnum;
import com.example.pcbackend.globa.GlobalException;
import com.example.pcbackend.pojo.LoginTicket;
import com.example.pcbackend.pojo.SysUser;
import com.example.pcbackend.service.RedisService;
import com.example.pcbackend.service.ScanQrcodeLoginService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.concurrent.locks.ReentrantLock;

/***
 * @title ScanQrcodeLoginServiceImpl
 * @description <description class purpose>
 * @author WeiShuo
 * @version 1.0.0
 * @create 2023/10/4 20:20
 **/
@Service
public class ScanQrcodeLoginServiceImpl implements ScanQrcodeLoginService {

    @Autowired
    private RedisService redisService;

    private ReentrantLock lock = new ReentrantLock();

    /**
     * 认证 accessToken 是在 filter实现；并且认证 临时token是否是有效二维码
     *
     * @param token
     */
    @Override
    public void authAccessToken(String token) {

        // 避免多个移动端同时扫描同一个二维码
        lock.lock();
        try {

            /**
             * 用户认证 accessToken 是在JwtAuthTokenFilter 实现
             */
            SysUser user = UserContext.getUser();
            if (user == null) {
                throw new GlobalException("用户未登录");
            }

            Object o = redisService.get(token);
            if (o == null) {
                throw new GlobalException("二维码无效");
            }
            LoginTicket loginTicket = (LoginTicket) o;

            //二维码状态如果不是待扫描，说明此临时凭证无效
            if (!loginTicket.getStatusCode().equals(QrCodeStatusEnum.WAITING.getStatusCode())) {
                throw new GlobalException("二维码无效");
            }

            // 修改扫码状态
            loginTicket.setStatusCode(QrCodeStatusEnum.SCANNED.getStatusCode());
            // 将二维码与用户进行关联
            loginTicket.setUsername(user.getUsername());
            redisService.set(token, loginTicket, 5 * 60L);

        } finally {
            lock.unlock();
        }
    }

    /**
     * 确认登录
     *
     * @param token         临时扫码登录凭证
     * @param operationType 操作类型  confirm：确认 ；cancel：取消登录             、
     */
    @Override
    public void confirm(String token, String operationType) {

        /**
         * 用户认证 accessToken 是在JwtAuthTokenFilter 实现
         */
        SysUser user = UserContext.getUser();
        if (user == null) {
            throw new GlobalException("用户未登录");
        }

        Object o = redisService.get(token);
        if (o == null) {
            throw new GlobalException("二维码无效");
        }
        LoginTicket loginTicket = (LoginTicket) o;

        //二维码状态如果不是待确认，说明此临时凭证无效
        if (!loginTicket.getStatusCode().equals(QrCodeStatusEnum.SCANNED.getStatusCode())) {
            throw new GlobalException("二维码无效");
        }

        //判断AccessToken 用户与之前待确认用户，是否是同一个用户
        if (!user.getUsername().equals(loginTicket.getUsername())) {
            throw new GlobalException("二维码无效");
        }


        if (operationType.equals("confirm")) {
            lock.lock();
            try {
                loginTicket.setStatusCode(QrCodeStatusEnum.CONFIRMED.getStatusCode());
                redisService.set(token, loginTicket, 5 * 60L);
            } finally {
                lock.unlock();
            }
        } else if (operationType.equals("cancel")) {
            lock.lock();
            try {
                loginTicket.setStatusCode(QrCodeStatusEnum.CANCEL.getStatusCode());
                redisService.set(token, loginTicket, 5 * 60L);
            } finally {
                lock.unlock();
            }
        }
    }




}
